<template>
	<view @click="showCity = !props.disabled ? !showCity : false">
		<!-- #ifdef APP-NVUE -->
		<view :eventPenetrationEnabled="true">
			<slot></slot>
		</view>
		<!-- #endif -->
		<!-- #ifndef APP-NVUE -->
		<slot></slot>
		<!-- #endif -->
		<tm-drawer :zIndex="props.zIndex" :inContent="props.inContent" :disabbleScroll="true" :round="props.round"
			ref="drawer" :height="dHeight" :closeable="true" :overlayClick="aniover" @open="drawerOpen" @cancel="cancel"
			@ok="confirm" :show="showCity" @close="closeDrawer" title="请选择" ok-text="确认">
			<tm-picker-view v-if="showCity" :dataKey="props.mapKey || props.dataKey"
				:map-key="props.mapKey || props.dataKey" :height="dHeight - 230" @end="aniover = true"
				@start="aniover = false" :modelValue="_colIndex" @update:modelValue="_colIndex = $event"
				@update:model-str="_colStr = $event" :model-str="_colStr" :default-value="_colIndex"
				:beforeChange="props.beforeChange" :immediateChange="props.immediateChange" :columns="_data">
			</tm-picker-view>
			<tm-button label="确认选择" block :margin="[32, 12]" :color="props.color" :linear="props.linear"
				:linear-deep="props.linearDeep" @click="confirm" :round="props.btnRound">
			</tm-button>
			<view :style="{ height: sysinfo.bottomSafe + 'px' }"></view>
		</tm-drawer>
	</view>
</template>
<script lang="ts" setup>
	/**
 * 级联选择（弹层）
 * @description 这是弹出式级联
 */
	import { PropType, Ref, ref, watchEffect, onMounted, getCurrentInstance, computed, toRaw, inject, nextTick, watch } from 'vue'
	import { custom_props } from '../../tool/lib/minxs'
	import tmDrawer from '../tm-drawer/tm-drawer.vue'
	import { columnsItem } from '../tm-picker-view/interface'
	import tmPickerView from '../tm-picker-view/tm-picker-view.vue'
	import TmSheet from '../tm-sheet/tm-sheet.vue'
	import tmText from '../tm-text/tm-text.vue'
	import tmButton from '../tm-button/tm-button.vue'
	import { useWindowInfo } from '../../tool/useFun/useWindowInfo'

	const drawer = ref<InstanceType<typeof tmDrawer> | null>(null)
	const proxy = getCurrentInstance()?.proxy ?? null

	/**
	 * 事件说明：
	 * v-model:show 双向绑定显示和隐藏选择器
	 * v-model 双向绑定以selectedModel为模式的值。一般用来给数据库后台用的。
	 * v-model:model-str 单向输出地区名称，
	 * 一般用来绑定在Input组件或者其它组件上用来展示当前选择的地址名称，
	 * 但我们服务器可能有的是id或者index，所以你可以v-model绑定数据，用此v-model:model-str来显示数据。
	 * confirm 点击了确认按钮时触发，返回当前选择数据。
	 * cancel 取消或者点击遮罩关闭了选择器都将触发。
	 */
	const emits = defineEmits(['update:show', 'update:modelValue', 'update:modelStr', 'confirm', 'cancel', 'close', 'open'])
	const props = defineProps({
		...custom_props,

		//可v-model,每一列选中的索引值
		modelValue: {
			type: Array as PropType<Array<number | string>>,
			default: () => []
		},
		/**
		 * 注意：这里是单向输出显示的value值，而不是modelValue的index索引值。
		 * 这里主要是为了方便表单上页面的显示。如果真要保存到数据库，你应该保存modelValue的值。
		 */
		modelStr: {
			type: [String],
			default: ''
		},
		//默认选中的索引值。
		defaultValue: {
			type: Array as PropType<Array<number | string>>,
			default: () => []
		},
		//赋值和选值方式
		//name:名称模式赋值和选择
		//id:id模式赋值和选择
		//index:索引模式赋值和选择
		selectedModel: {
			type: String,
			default: 'index'
		},
		//数据。
		columns: {
			type: Array as PropType<Array<columnsItem>>,
			default: () => [],
			required: true
		},
		//当columns项目中的data数据为对象时的key取值字段。
		dataKey: {
			type: String,
			default: 'text'
		},
		//当columns项目中的data数据为对象时的key取值字段。兼容上方dataKey,因为微信dataKey与本字段重名，无法设置。
		mapKey: {
			type: String,
			default: 'text'
		},
		//当前改变index项时，改变时执行的函数。如果返回false，将会阻止本次改变,可以是Promise
		//提供了即将改变的数据和将要改变到目标的数据
		//结构 为 from:{itemindex,levelIndex,data},to:{itemindex,levelIndex,data}。
		beforeChange: {
			type: [Boolean, Function],
			default: () => false
		},
		//v-model:show来双向绑定显示和隐藏选择器。
		show: {
			type: [Boolean],
			default: false
		},
		color: {
			type: String,
			default: 'primary'
		},
		linear: {
			type: String,
			default: ''
		},
		linearDeep: {
			type: String,
			default: 'light'
		},
		btnRound: {
			type: Number,
			default: 0
		},
		round: {
			type: Number,
			default: 12
		},
		height: {
			type: Number,
			default: 700
		},
		immediateChange: {
			type: Boolean,
			default: false
		},
		/** 是否嵌入弹层，开启后将在它的父组件内执行弹层。 */
		inContent: {
			type: Boolean,
			default: false
		},
		/**禁用时，通过插槽点击时，不会触发显示本组件，适合表单 */
		disabled: {
			type: Boolean,
			default: false
		},
		zIndex: {
			type: [Number, String],
			default: 999
		},
		//弹出的动画时间单位ms.
		duration: {
			type: Number,
			default: 300
		}
	})
	const showCity = ref(true)
	const _colIndex : Ref<Array<number>> = ref([])
	const _data = computed(() => props.columns)
	const _colStr = ref(props.modelStr)
	const aniover = ref(true)
	const sysinfo = useWindowInfo()

	let tmid : any = NaN
	watchEffect(() => {
		showCity.value = props.show
	})

	watch(
		[() => props.columns, () => props.modelValue],
		() => {
			clearTimeout(tmid)
			tmid = setTimeout(function () {
				getIndexBymodel(_data.value, props.selectedModel, 0, props.modelValue)
				defaultModerStrGet()
			}, 500)
		},
		{ deep: true }
	)

	function closeDrawer(e : boolean) {
		showCity.value = e
		emits('update:show', showCity.value)
		getIndexBymodel(_data.value, props.selectedModel, 0, props.modelValue)
		emits('close')
	}

	//弹层打开时触发。
	function drawerOpen() {
		emits('open')
	}
	onMounted(() => {
		
		// getIndexBymodel(_data.value, props.selectedModel, 0, props.defaultValue)
		if (props.defaultValue.length > 0) {
			getIndexBymodel(_data.value, props.selectedModel, 0, props.defaultValue)


			defaultModerStrGet()
		}
	})
	//点击确认了地区。
	function confirm() {
		// if (!aniover.value) return
		if (_colIndex.value.length == 0) {
			getIndexBymodelByEmptyOnConfirm(_data.value, props.selectedModel, 0, props.defaultValue)
		}
		setVal()
		nextTick(() => {
			emits('confirm', toRaw(_colIndex.value))
			drawer.value?.close()
		})
	}
	function cancel() {
		if (!aniover.value) return
		emits('cancel')
	}
	function setVal() {
		let val = []
		if (props.selectedModel == 'name') {
			val = _colStr.value.split('/') ?? []
		} else if (props.selectedModel == 'id') {
			val = getRouterId(_data.value, 0)
		} else {
			val = [..._colIndex.value]
		}
		emits('update:modelValue', val)
		emits('update:modelStr', _colStr.value)
	}
	function defaultModerStrGet() {
		clearTimeout(tmid)
		tmid = setTimeout(function () {

			if (!_colStr.value && _colIndex.value.length > 0) {
				let text = getRouterText(_data.value, 0)
				let str = text.join('/')
				emits('update:modelStr', str)

			}
			if (_colIndex.value.length == 0) {
				emits('update:modelStr', '')
			}
		}, 100)
	}
	//模拟模型来返回index值
	function getIndexBymodel(vdata : Array<columnsItem> = [], model = 'name', parentIndex : number = 0, value : Array<number | string> = []) : Array<number> {
		if (value.length == 0) {
			_colIndex.value = []
			return []
		}
		let p_colIndex = [..._colIndex.value]
		_colIndex.value = []


		if (model == 'name') {
			let item = vdata.filter((el) => value[parentIndex] == el['text'])
			if (item.length == 0) {
				//    如果不存在,不再默认选中第一个,2022年10月14日修改
				// item = vdata[0];
				// if (item) {
				//     value[parentIndex] = item['text'];
				//     p_colIndex[parentIndex] = 0
				//     if (item['children']) {
				//         getIndexBymodel(item['children'], model, parentIndex + 1, value);
				//     }
				// }
			} else {
				item = item[0]
				if (item) {
					p_colIndex[parentIndex] = vdata.findIndex((el) => el['text'] == item['text'])
					if (item['children']) {
						getIndexBymodel(item['children'], model, parentIndex + 1, value)
					}
				}
			}
		} else if (model == 'id') {
			let item = vdata.filter((el) => value[parentIndex] == el['id'])

			if (item.length == 0) {
				//    如果不存在,不再默认选中第一个,2022年10月14日修改
				// item = vdata[0];
				// if (item) {
				//     value[parentIndex] = item['id'];
				//     p_colIndex[parentIndex] = 0
				//     if (item['children']) {
				//         getIndexBymodel(item['children'], model, parentIndex + 1, value);
				//     }
				// }
			} else {
				item = item[0]
				if (item) {
					p_colIndex[parentIndex] = vdata.findIndex((el) => el['id'] == item['id'])
					if (item['children']) {
						getIndexBymodel(item['children'], model, parentIndex + 1, value)
					}
				}
			}
		} else {
			p_colIndex = [...value]
		}
		_colIndex.value = [...p_colIndex]

		return _colIndex.value
	}
	// 和上方一样的功能,区别是,当什么都不选的时候,点了确认,就要默认选中第一行数据.
	function getIndexBymodelByEmptyOnConfirm(
		vdata : Array<columnsItem> = [],
		model = 'name',
		parentIndex : number = 0,
		value : Array<number | string> = []
	) : Array<number> {
		let p_colIndex = [..._colIndex.value]
		_colIndex.value = []
		if (model == 'name') {
			let item = vdata.filter((el) => value[parentIndex] == el[props.mapKey])
			if (item.length == 0) {
				//    如果不存在,不再默认选中第一个,2022年10月14日修改
				item = vdata[0]
				if (item) {
					value[parentIndex] = item[props.mapKey]
					p_colIndex[parentIndex] = 0
					if (item['children']) {
						getIndexBymodel(item['children'], model, parentIndex + 1, value)
					}
				}
			} else {
				item = item[0]
				if (item) {
					p_colIndex[parentIndex] = vdata.findIndex((el) => el[props.mapKey] == item[props.mapKey])
					if (item['children']) {
						getIndexBymodel(item['children'], model, parentIndex + 1, value)
					}
				}
			}
		} else if (model == 'id') {
			let item = vdata.filter((el) => value[parentIndex] == el['id'])
			if (item.length == 0) {
				//    如果不存在,不再默认选中第一个,2022年10月14日修改
				item = vdata[0]
				if (item) {
					value[parentIndex] = item['id']
					p_colIndex[parentIndex] = 0
					if (item['children']) {
						getIndexBymodel(item['children'], model, parentIndex + 1, value)
					}
				}
			} else {
				item = item[0]
				if (item) {
					p_colIndex[parentIndex] = vdata.findIndex((el) => el['id'] == item['id'])
					if (item['children']) {
						getIndexBymodel(item['children'], model, parentIndex + 1, value)
					}
				}
			}
		} else {
			p_colIndex = [...value]
		}
		_colIndex.value = [...p_colIndex]
		return _colIndex.value
	}
	//返回 一个节点从父到子的路径id组。
	function getRouterId(list = [], parentIndex = 0) : Array<string | number> {
		let p : Array<string | number> = []
		for (let i = 0; i < list.length; i++) {
			if (i == _colIndex.value[parentIndex]) {
				p.push(list[i]['id'])
				if (typeof _colIndex.value[parentIndex] != 'undefined') {
					let c = getRouterId(list[i]['children'], parentIndex + 1)
					p = [...p, ...c]
				}
				break
			}
		}
		return p
	}
	//返回 一个节点从父到子的路径text组。
	function getRouterText(list : Array<childrenData> = [], parentIndex = 0) : Array<string | number> {
		let p : Array<string | number> = []
		for (let i = 0; i < list.length; i++) {
			if (i == _colIndex.value[parentIndex]) {

				p.push(list[i][props.mapKey || "text"])
				if (typeof _colIndex.value[parentIndex] != 'undefined') {
					let c = getRouterText(list[i]['children'], parentIndex + 1)
					p = [...p, ...c]
				}
				break
			}
		}
		return p
	}
	const dHeight = computed(() => {
		return props.height + sysinfo.bottomSafe + 80
	})
</script>